package containerlogistik.implementation;

import containerlogistik.interfaces.Acceleration;
import static containerlogistik.implementation.Values.*;
import static com.google.common.base.Preconditions.*;
import containerlogistik.interfaces.Level;
import containerlogistik.interfaces.Speed;
import containerlogistik.interfaces.TimeDiff;

public class AccelerationInMs2 extends AbstractValue<Acceleration> implements Acceleration {
        
    private final double ms2;

    private AccelerationInMs2(double ms2) {
        this.ms2 = ms2;
    }

    static AccelerationInMs2 valueOf(double ms2) {
        return new AccelerationInMs2(ms2);
    }

    @Override
    public double ms2() {
        return this.ms2;
    }

    @Override
    public boolean isZero() {
        return (this.equals(ZERO_ACCELERATION));
    }

    @Override
    public boolean isValid() {
        return true;
    }

    @Override
    public String toString() {
        return String.format("AccelerationInMs2{ms2=%.2f}",
                this.ms2());
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) return true;
        if (!(obj instanceof Acceleration)) return false;
        return this.compareTo((Acceleration)obj) == 0;
    }

    @Override
    public int hashCode() {
        return hashDouble(this.ms2());
    }

    @Override
    public int compareTo(Acceleration o) {
        return Double.compare(this.ms2(), o.ms2());
    }

    @Override
    public Acceleration add(Acceleration value) {
        return accelerationInMs2(this.ms2() + value.ms2());
    }

    @Override
    public Acceleration sub(Acceleration value) {
        return accelerationInMs2(this.ms2() - value.ms2());
    }

    @Override
    public Acceleration mul(double factor) {
        return accelerationInMs2(this.ms2() * factor);
    }

    @Override
    public Acceleration div(double factor) {
        checkArgument(factor != 0, "can not divide zero: %s", factor);
        return accelerationInMs2(this.ms2() / factor);
    }

    @Override
    public Acceleration inverse() {
        return accelerationInMs2(-this.ms2());
    }

    @Override
    public double div(Acceleration value) {
        checkArgument(value.equals(ZERO_ACCELERATION), 
                "can not divide zero: %s", value);
        return (this.ms2() / value.ms2());
    }

    @Override
    public Speed mul(TimeDiff time) {
        return speedInMS(this.ms2() * time.s());
    }

    @Override
    public Acceleration mul(Level value) {
        return accelerationInMs2(this.ms2() * value.g());
    }
}
